#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#define SIZE 1024
#define MAX_ARGV 100
#define SEP " "
char pwd[SIZE];
char *argv[MAX_ARGV];
char env[SIZE]; // for test
int lastcode = 0;
char *HostName()
{
    return getenv("HOSTNAME") ? getenv("HOSTNAME") : "None";
}
char *UserName()
{
    return getenv("USER") ? getenv("USER") : "None";
}
char *CurrentWorkDir()
{
    return getenv("PWD") ? getenv("PWD") : "None";
}
int Interactive(char out[], int size)
{
    // 输出提示符并获取用户的输入字符串
    printf("[%s@%s %s]$ ", UserName(), HostName(), CurrentWorkDir());
    fgets(out, SIZE, stdin); // 注意:输入的时候需要使用fgets进行读取
    // 去掉换行符
    out[strlen(out) - 1] = '\0';
    return strlen(out); // 返回长度
}
void Split(char in[])
{
    int i = 0;
    argv[i++] = strtok(in, SEP);
    while (argv[i++] = strtok(NULL, SEP)); // 这里自动会将最后设置为NULL,最后必须以NULL结尾
    if(strcmp(argv[0], "ls") == 0)
    {
        argv[i-1] = (char*)"--color";
        argv[i] = NULL;
    }
}
void Execute()
{
    pid_t id = fork();
    if (id == 0)
    {
        // 子进程
        execvp(argv[0], argv);
        exit(100);
    }
    // 回收子进程
    int status;
    waitpid(id, &status, 0);
    lastcode = WEXITSTATUS(status);
}
int BuildinCmd()
{
    int ret = 0;
    // 是就返回1,不是就返回0
    if (strcmp(argv[0], "exit") == 0)
    {
        exit(0);
    }
    else if (strcmp(argv[0], "cd") == 0)
    {
        if (argv[1] == NULL)
        {
            chdir(getenv("HOME"));
        }
        else
        {
            chdir(argv[1]);
        }
        // 将PWD环境变量更新
        // putenv的参数是key=value的形式,需要使用snprintf进行拼接
        char temp[SIZE];
        getcwd(temp, SIZE); // 获取当前工作目录
        snprintf(pwd, SIZE, "PWD=%s", temp);
        putenv(pwd); // 更新环境变量
        ret = 1;
    }
    else if (strcmp(argv[0], "export") == 0)
    {
        ret = 1;
        if (argv[1])
        {
            strcpy(env, argv[1]);
            putenv(env);
        }
    }
    else if (strcmp(argv[0], "echo") == 0)
    {
        ret = 1;
        if (argv[1] == NULL)
        {
            printf("\n");
        }
        else
        {
            if (argv[1][0] == '$')
            {
                if (argv[1][1] == '?')
                {
                    printf("%d\n", lastcode);
                    lastcode = 0;
                }
                // 如果是环境变量
                else
                {
                    char *env_value = getenv(argv[1] + 1);
                    if (env_value)
                    {
                        printf("%s\n", env_value);
                    }
                }
            }
            else
            {
                // 普通字符串
                printf("%s\n", argv[1]);
            }
        }
    }
    return ret;
}
int main()
{
    while (1)
    {
        char commandline[SIZE];

        int n = Interactive(commandline, SIZE);
        if (n == 0)
            continue; // 处理空串

        // 读取用户输入的命令
        Split(commandline);

        // 处理内建命令
        n = BuildinCmd();
        if (n)
            continue;

        // 执行命令
        Execute();
    }
    return 0;
}